package com.zlq.cn.service.un;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlq.cn.api.ResponseException;
import com.zlq.cn.bootstrap.SignApiBootstrap;
import com.zlq.cn.cache.RedisCacheService;
import com.zlq.cn.cache.RedisKey;
import com.zlq.cn.cache.topic.RedisTopicService;
import com.zlq.cn.config.Config;
import com.zlq.cn.config.FinderConfiguration;
import com.zlq.cn.dto.DataCountDTO;
import com.zlq.cn.dto.DateCountDTO;
import com.zlq.cn.entity.SmsRecord;
import com.zlq.cn.entity.User;
import com.zlq.cn.entity.UserMsg;
import com.zlq.cn.entity.VipLevel;
import com.zlq.cn.enums.UserMsgEnum;
import com.zlq.cn.mapper.un.UserMapper;
import com.zlq.cn.util.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhoucl
 * @since 2020-06-08
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
    @Resource
    private RedisCacheService redisCacheService;
    @Resource
    private VipLevelService vipLevelService;
    @Resource
    private SmsRecordService smsRecordService;
    @Resource
    private FinderConfiguration finderConfiguration;
    @Resource
    private RedisTopicService redisTopicService;
    @Resource
    private PushService pushService;
    @Resource
    private UserMsgService userMsgService;

    public User findUserByToken(String token) {
        User user = null;
        String userId = redisCacheService.get(RedisKey.createUserTokenKey(token));
        if (userId != null) {
            user = getUserByIdCache(userId);
        }
        return user;
    }

    /**
     * 用户登录，没有则创建
     */
    public User updateLogin(String phone, String vcode, String platform, boolean isBind) {
        // 不是绑定用户校验验证码或者不是测试环境需要验证
        if (!isBind) {
            if (!smsRecordService.findCheckSmsVcode(phone, vcode, SmsRecord.SMS_TYPE_LOGIN)) {
                ResponseException.resultApiError("验证码错误");
            }
        }
        // 校验该手机号是否存在
        User user = getOne(new QueryWrapper<User>().lambda().eq(User::getPhone, phone));
        if (user == null) {
            user = new User();
            user.setToken(StringUtils.createToken());
            user.setPhone(phone);
            user.setIsDisable(0);
            user.setVipLevel(0);
            user.setInvitationCode(createInvitationCode(6));
            user.setPhoneModel(StringUtils.iphoneModel(platform));
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            user.setNewCreate(true);
            int xxx = baseMapper.insert(user);
            UserMsg userMsg = new UserMsg();
            userMsg.setMsgType(UserMsgEnum.FRIEND_SYSTEM_REMINDER.getType());
            userMsg.setFromUserId(0);
            userMsg.setToUserId(user.getId());
            userMsg.setContent(UserMsgEnum.FRIEND_SYSTEM_REMINDER.getMsgContent());
            userMsg.setCreateTime(LocalDateTime.now());
            userMsg.setUpdateTime(LocalDateTime.now());
            userMsgService.save(userMsg);
            pushService.pushAccount(user.getProject(), Collections.singletonList(user.getId()),
                    UserMsgEnum.FRIEND_SYSTEM_REMINDER.getMsgTitle(),
                    UserMsgEnum.FRIEND_SYSTEM_REMINDER.getMsgContent(), null);
            // 不是绑定用户跟新token
        } else if (!isBind) {
            // 更新token
            redisCacheService.del(RedisKey.createUserTokenKey(user.getToken()));
            user.setToken(StringUtils.createToken());
            user.setPhoneModel(StringUtils.iphoneModel(platform));
            user.setUpdateTime(LocalDateTime.now());
            baseMapper.updateUserToken(user);
        }
        user.setIsNotVipAddFriend(Config.IS_NOT_VIP_ADD_FRIEND);
        user.setConfigUrl(finderConfiguration.getConfigUrl());
        user.setCurrentDate(LocalDateTime.now());
        updateSurplusDay(user);
        setUserTokenUserId(user);
        return user;
    }

    public String createInvitationCode(int length) {
        String invitationCode = StringUtils.getRandomByLength(length);
        User user = getOne(new QueryWrapper<User>().lambda().eq(User::getInvitationCode, invitationCode));
        while (user != null) {
            invitationCode = StringUtils.getRandomByLength(length);
            user = getOne(new QueryWrapper<User>().lambda().eq(User::getInvitationCode, invitationCode));
        }
        return invitationCode;
    }

    public void setUserTokenUserId(User user) {
        setUserByIdCache(user);
        redisCacheService.set(RedisKey.createUserTokenKey(user.getToken()), user.getId() + "");
    }

    /**
     * 修改头像或者名称
     *
     * @param user
     */
    public void updateUserAvatarAndNameAndGender(User user) {
        User loginUser = SignApiBootstrap.requestUser();
        if (StringUtils.isNotEmpty(user.getAvatar())) {
            loginUser.setAvatar(user.getAvatar());
        }
        if (StringUtils.isNotEmpty(user.getName())) {
            loginUser.setName(user.getName());
        }
        if (StringUtils.isNotEmpty(user.getGender())) {
            loginUser.setGender(user.getGender());
        }
        if (Objects.nonNull(user.getBirthday())) {
            loginUser.setBirthday(user.getBirthday());
        }
        setUserByIdCache(loginUser);
        user.setId(loginUser.getId());
        baseMapper.updateUserInfo(user);
    }

    public void updateVipTime(String orderType, User loginUser) {
        VipLevel vipLevelEmpty = vipLevelService.getOne(new LambdaQueryWrapper<VipLevel>().eq(VipLevel::getVipKey, orderType));
        if (vipLevelEmpty == null) {
            ResponseException.resultApiError("订单类型异常");
        } else {
            if (loginUser.getVipLevel() != null && loginUser.getVipLevel() < vipLevelEmpty.getId()) {
                loginUser.setVipLevel(vipLevelEmpty.getId());
            }
        }

        LocalDateTime vipStartTime = loginUser.getVipStartTime();
        LocalDateTime vipEndTime = loginUser.getVipEndTime();
        if (vipStartTime == null) {// 初次开通，直接增加时间
            vipStartTime = LocalDateTime.now();
            loginUser.setVipStartTime(vipStartTime);
            loginUser.setVipEndTime(vipStartTime.plusMonths(vipLevelEmpty.getVipMonthNum()).plusDays(vipLevelEmpty.getVipDayNum()));
        } else if (vipEndTime != null) {// 开通过
            if (vipEndTime.isBefore(LocalDateTime.now())) {// 校验是否过期,过期则开始结束重新生成
                vipStartTime = LocalDateTime.now();
                loginUser.setVipStartTime(vipStartTime);
                loginUser.setVipEndTime(vipStartTime.plusMonths(vipLevelEmpty.getVipMonthNum()).plusDays(vipLevelEmpty.getVipDayNum()));
            } else {
                loginUser.setVipEndTime(vipEndTime.plusMonths(vipLevelEmpty.getVipMonthNum()).plusDays(vipLevelEmpty.getVipDayNum()));
            }
        }
        baseMapper.updateVipTime(loginUser);
        setUserByIdCache(loginUser);
    }

    public void updateSurplusDay(User user) {
        if (user == null) return;
        LocalDateTime vipEndTime = user.getVipEndTime();
        long surplusDay = 0;
        if (vipEndTime != null && vipEndTime.isAfter(LocalDateTime.now())) {
            surplusDay = Math.abs(vipEndTime.toLocalDate().until(LocalDate.now(), ChronoUnit.DAYS));
        }
        user.setSurplusDay(surplusDay);
        if (user.getVipEndTime() != null) {
            user.setMembershipExpirationDate(String.format("您的会员将于%s日到期", DateTimeFormatter.ofPattern("yyyy-MM-dd").format(user.getVipEndTime())));
        }
        if (user.getSurplusDay() == 0 && user.getVipLevel() > 0) {
            user.setVipLevel(0);
            update(new LambdaUpdateWrapper<User>().set(User::getVipLevel, 0).eq(User::getId, user.getId()));
        }
    }

    public boolean updateLocationResetCount(User loginUser) {
        if (loginUser.getLocationResetCount() < finderConfiguration.getLocationResetCount()) {
            loginUser.setLocationResetCount(loginUser.getLocationResetCount() + 1);
            updateById(loginUser);
            setUserByIdCache(loginUser);
            return true;
        } else {
            ResponseException.resultApiError("清除次数上限");
        }
        return false;
    }

    public void updateBatchLocationLogInfo(List<User> modifyUsers, Map<Integer, User> execUserMap) {
        if (modifyUsers.isEmpty()) return;
        for (User modifyUser : modifyUsers) {
            User userCache = execUserMap.get(modifyUser.getId());
            if (userCache != null) {
                userCache.setLatitude(modifyUser.getLatitude());
                userCache.setLongitude(modifyUser.getLongitude());
                userCache.setAddress(modifyUser.getAddress());
                userCache.setBattery(modifyUser.getBattery());
                userCache.setNetworkType(modifyUser.getNetworkType());
                // 处理电量小于30%发送推送
                if (userCache.getBattery() <= finderConfiguration.getMinBattery() && !userCache.isBatteryWarningPush()) {
                    userCache.setBatteryWarningPush(true);
                    redisTopicService.aliPushBatteryWarningConvertAndSend(userCache);
                } else if (userCache.getBattery() > finderConfiguration.getMinBattery()) {
                    userCache.setBatteryWarningPush(false);
                }
                setUserByIdCache(userCache);
            }
        }
        updateBatchById(modifyUsers);
    }

    public User getUserByIdCache(String userId) {
        return redisCacheService.get(RedisKey.createUserKey(userId));
    }

    public User getUserByIdCache(int userId) {
        return getUserByIdCache(userId + "");
    }

    public void setUserByIdCache(User user) {
        redisCacheService.set(RedisKey.createUserKey(user.getId()), user);
    }

    public void clearUserCache(User user) {
        redisCacheService.del(RedisKey.createUserKey(user.getId()));
        redisCacheService.del(RedisKey.createUserTokenKey(user.getToken()));
    }

    public List<DataCountDTO> totalCount(DateCountDTO dateCountDTO) {
        List<DataCountDTO> dataCountDTOS = new ArrayList<>();
        long days = Math.abs(dateCountDTO.getEndTime().until(dateCountDTO.getStartTime(), ChronoUnit.DAYS));
        for (long i = 0; i < days; i++) {
            DataCountDTO dataCountDTO = new DataCountDTO();
            dataCountDTO.setCountField(dateCountDTO.getEndTime().minusDays(i).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            dataCountDTO.setCountResult(0);
            dataCountDTOS.add(dataCountDTO);
        }
        List<DataCountDTO> queryList = baseMapper.totalCount(dateCountDTO);
        int total = 0;
        for (DataCountDTO dataCountDTO : dataCountDTOS) {
            if (CollectionUtils.isNotEmpty(queryList)) {
                for (DataCountDTO countDTO : queryList) {
                    if (countDTO.getCountField().equals(dataCountDTO.getCountField())) {
                        dataCountDTO.setCountResult(countDTO.getCountResult());
                        break;
                    }
                }
            }
            total += dataCountDTO.getCountResult();
        }
        DataCountDTO dataCountDTO = new DataCountDTO();
        dataCountDTO.setCountField("近7天总计");
        dataCountDTO.setCountResult(total);
        dataCountDTOS.add(0, dataCountDTO);
        return dataCountDTOS;
    }
}
